//knockout functions

ko.onDemandObservable = function (callback, target) {
    var _value = ko.observable();  //private observable

    var result = ko.dependentObservable({
        read: function () {
            //if it has not been loaded, execute the supplied function
            if (!result.loaded()) {
                callback.call(target);
            }
            //always return the current value
            return _value();
        },

        write: function (newValue) {
            //indicate that the value is now loaded and set it
            result.loaded(true);
            _value(newValue);
        },

        deferEvaluation: true  //do not evaluate immediately when created
    });

    //expose the current state, which can be bound against
    result.loaded = ko.observable();
    
    //load it again
    result.refresh = function () {
        result.loaded(false);
    };

    return result;
};

ko.dirtyFlag = function (root, isInitiallyDirty) {
    var result = function () { }
    var _initialState = ko.observable(ko.toJSON(root));
    var _isInitiallyDirty = ko.observable(isInitiallyDirty);

    result.isDirty = ko.dependentObservable(function () {
        return _isInitiallyDirty() || _initialState() !== ko.toJSON(root);
    });

    result.reset = function () {
        _initialState(ko.toJSON(root));
        _isInitiallyDirty(false);
    };

    return result;
};

ko.bindingHandlers.fadeVisible = {
    init: function (element, valueAccessor) {
        // Initially set the element to be instantly visible/hidden depending on the value
        var value = valueAccessor();
        $(element).toggle(ko.utils.unwrapObservable(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
    },
    update: function (element, valueAccessor) {
        // Whenever the value subsequently changes, slowly fade the element in or out
        var value = valueAccessor();
        addToAnimate(ko.utils.unwrapObservable(value) ? $(element).fadeIn() : $(element).fadeOut());
    }
};

//knockout models

//container model
var viewModel = {};

// view (for example, errors) model
viewModel.viewEventModel = {
    events: ko.observableArray([]),

    addEvent: function (event) {
        var container = $("<div/>");
        container.html(event.eventBody);
        //event.eventBody = container.text();
        event.eventBody = container.html();
        this.events.push(event);
    },

    removeEvent: function (event) {
        this.events.remove(event);
    },

    removeAllEvents: function () {
        this.events.removeAll();
    }
};

//site map model
var viewSiteMapModel = function (parentNodeId, addAction) {
    var innerAddAction = addAction;
    this.ParentNodeId = ko.observable(parentNodeId);
    this.NodeTitle = ko.observable('');
    this.NodeDescription = ko.observable('');
    this.NodeUrl = ko.observable('');
    this.IsVisible = ko.observable(true);
    this.isReady = ko.observable(false);

    this.viewSiteMapAddNode = function () {
        this.viewSiteMapRemoveNode();
        this.isReady(true);
    };

    this.viewSiteMapRemoveNode = function () {
        this.NodeTitle('');
        this.NodeDescription('');
        this.NodeUrl('');
        this.IsVisible(true);
    };

    this.viewSiteMapSaveNew = function () {
        if (innerAddAction) {
            var params = ko.toJSON(this);
            innerAddAction(params);
        }
        this.isReady(false);
    };

    this.viewSiteMapEnabled = ko.dependentObservable(function () {
        return this.isReady();
    }, this);
};

//media file
var mediaContentTags = new function () {
    var _allTags = [];
    var _isLoaded = false;

    this.all = function () {
        if (!_isLoaded) {
            $.ajax({
                type: 'POST',
                dataType: 'json',
                async: false,
                url: $.cmsAdminOptions.options.knownUrls.allMediaContentTagsUrl,
                success: function (data) {
                    _allTags = data;
                    _isLoaded = true;
                }
            });
        }
        return _allTags;
    };
};

function mediaFile(fileName, fileId, linkedFileName) {
    this.fileName = ko.observable(fileName);
    this.fileId = ko.observable(fileId);
    this.linkedFileName = ko.observable(linkedFileName);
    this.name = ko.observable();
    this.description = ko.observable();
    this.allTags = ko.observableArray(mediaContentTags.all()),
    this.tags = ko.observableArray([]);
    this.selected = ko.observable(false);
    this.dirtyFlag = new ko.dirtyFlag(this, false);
    this.blockFromSearchEngines = ko.observable(false); ;
}

viewModel.mediaFileModel = {
    files: ko.observableArray([]),

    uploadedFile: function (file) {
        this.files.push(file);
    },

    clearContent: function (event) {
        if (event) {
            var fileId = $(event.target).parent().children(':hidden').val();
            var selectedFile = viewModel.mediaFileModel.currentlySelected();
            if (selectedFile.dirtyFlag.isDirty()) {
                selectedFile.name('');
                selectedFile.description('');
                selectedFile.tags([]);
                selectedFile.selected(false);
            }
        }
    },

    toServer: function (mediaFolderId, callback) {
        var items = ko.toJS(this.files());
        var mappedItems = ko.utils.arrayMap(items, function (item) {
            delete item.allTags;
            delete item.selected;
            delete item.linkedFileName;
            if (!item.name) {
                item.name = item.fileName;
            }
            return item;
        });
        $.ajax({
            type: 'POST',
            url: $.cmsAdminOptions.options.knownUrls.createMediaContentUrl,
            data: JSON.stringify({ MediaId: mediaFolderId, Contents: mappedItems }),
            success: function (data) {
                callback(data.result, data.url);
            },
            contentType: 'application/json, charset=utf-8',
            dataType: 'json'
        });
    }
};

viewModel.mediaFileModel.currentlySelected = ko.dependentObservable(function () {
    return ko.utils.arrayFirst(this.files(), function (file) {
                return file.selected();
    });
}, viewModel.mediaFileModel);

viewModel.mediaFileModel.select = ko.dependentObservable({
    read: function () {
        return this.files();
    },
    write: function (file) {
        ko.utils.arrayForEach(this.files(), function (item) {
            item.selected(false);
        });
    },
    owner: viewModel.mediaFileModel
});

ko.applyBindings(viewModel);